/*
 * Copyright 2006-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.martinimix.service.payment.provider.cybersource;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.TimeZone;

import net.martinimix.domain.payment.CreditCardAuthorization;
import net.martinimix.service.payment.CreditCardTransactionFailedException;

/**
 * Provides a simple CyberSource response adapter.
 *  
 * @author Scott Rossillo
 *
 */
public class SimpleCyberSourceResponseAdapter implements
		CyberSourceResponseAdapter {
	
	/**
	 * Creates a new simple credit card transaction response adapter.
	 */
	public SimpleCyberSourceResponseAdapter() { }
	
	/**
	 * Returns a new credit card authorization command.
	 * 
	 * @return a new <code>CreditCardAuthorization</code>
	 */
	protected CreditCardAuthorization createResponseCommand() {
		return new CreditCardAuthorization();
	}
	
	/* (non-Javadoc)
	 * @see net.martinimix.service.payment.provider.cybersource.CyberSourceResponseAdapter#parseAuthorizationResponse(java.util.Map)
	 */
	public CreditCardAuthorization parseAuthorizationResponse(Map reply) {
		
		CreditCardAuthorization auth = createResponseCommand();
		String authAmount = (String) reply.get("ccAuthReply_amount");
		
		auth.setTypeCode("AUT");
		auth.setRequestId( (String) reply.get("requestID") );
		auth.setRequestToken( (String) reply.get("requestToken") );
		auth.setMerchantReferenceCode( (String) reply.get("merchantReferenceCode") );
		auth.setDecision( (String) reply.get("decision") );
		auth.setResponseCode( (String) reply.get("decision") );
		auth.setReasonCode( (String) reply.get("reasonCode") );
		auth.setCurrencyCode( (String) reply.get("purchaseTotals_currency") );
		auth.setBankAuthorization( (String) reply.get("ccAuthReply_authorizationCode") );
		auth.setAvsCode( (String) reply.get("ccAuthReply_avsCode") );
		auth.setCvCode(  (String) reply.get("ccAuthReply_cvCode") );
		auth.setAmexCapnAuthorizationCode( (String) reply.get("ccAuthReply_authRecord") );
		
		if(authAmount != null) {
			auth.setAmount(new BigDecimal( authAmount ));
			auth.setAuthorizationDate(parseDate( (String) reply.get("ccAuthReply_authorizedDateTime") ));
		} else {
			auth.setAuthorizationDate(new GregorianCalendar());
		}
		
		return auth;
	}
	
	/**
	 * Converts a date from CyberSource's standard date format to a calendar.
	 * 
	 * @param date a <code>String</code> containing the date to convert in the format
	 * <code>yyyy-MM-dd'T'HH:mm:ss'Z'</code>; may not be <code>null</code>
	 * 
	 * @return the <code>Calendar</code> value of the given <code>date</code>
	 */
	protected final Calendar parseDate(String date)  {
		
		Calendar cal = new GregorianCalendar();
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
		
		cal.setTimeZone(TimeZone.getTimeZone("GMT"));
		try {
			cal.setTime(format.parse(date));
		} catch (ParseException e) {
			throw new CreditCardTransactionFailedException(
					"Can't parse [" + date + "] with format [" + format.toPattern() + "]", e);
		}
		
		return cal;
	}

}
